Active Contours using Parameteric Curves

This tour explores image segmentation using parametric active contours.

Contents

Installing toolboxes and setting up the path.

You need to download the following files: signal toolbox, general toolbox and graph toolbox.

You need to unzip these toolboxes in your working directory, so that you have toolbox_signal, toolbox_general and toolbox_graph in your directory.

For Scilab user: you must replace the Matlab comment '%' by its Scilab counterpart '//'.

Recommandation: You should create a text file named for instance numericaltour.sce (in Scilab) or numericaltour.m (in Matlab) to write all the Scilab/Matlab command you want to execute. Then, simply run exec('numericaltour.sce'); (in Scilab) or numericaltour; (in Matlab) to run the commands.

Execute this line only if you are using Matlab.

getd = @(p)path(p,path); % scilab users must *not* execute this

Then you can add the toolboxes to the path.

getd('toolbox_signal/');
getd('toolbox_general/');
getd('toolbox_graph/');

Parameteric Curves

In this tours, the active contours are represented using parametric curve. It is implemented using a picewise linear curve, which is just a vector of complex numbers.

We compute an initial curve by performing subdivision of a control polygon.

Initial polygon.

c0 = [0.78 0.14 0.42 0.18 0.32 0.16 0.75 0.83 0.57 0.68 0.46 0.40 0.72 0.79 0.91 0.90]' + ...
 1i* [0.87 0.82 0.75 0.63 0.34 0.17 0.08 0.46 0.50 0.25 0.27 0.57 0.73 0.57 0.75 0.79]';

Interpolate the curve.

p = 256;
c1 = c0;
c1(end+1) = c1(1);
d = abs(c1(1:end-1)-c1(2:end)); d = [0;cumsum(d)];
c1 = interp1(d/d(end),c1,(0:p-1)'/p, 'linear');

Display the initial curve.

clf;
h = plot(c1([1:end 1]), 'k');
set(h, 'LineWidth', 2); axis('tight'); axis('off');

Compute the normal to the curve. This is obtained by rotating by pi/2 the tangent.

tgt = c1([2:end 1]) - c1([end 1:end-1]);
normal = -(1i*tgt)./abs(tgt);

Move the curve in the normal direction.

h = .03;
c2 = c1 + normal*h;
c3 = c1 - normal*h;

Display the curves.

clf;
hold on;
h = plot(c1([1:end 1]), 'k'); set(h, 'LineWidth', 2);
h = plot(c2([1:end 1]), 'r--'); set(h, 'LineWidth', 2);
h = plot(c3([1:end 1]), 'b--'); set(h, 'LineWidth', 2);
axis('tight'); axis('off');

Evolution by Mean Curvature

The simplest evolution is the mean curvature evolution, that is the evolution that reduces the length of the curve.

Time step for the evolution.

dt = 0.001;

Initialize the curve.

c = c1;

Compute the tangent using forward derivatives.

e1 = c([2:end 1]) - c;
e1 = e1 ./ abs(e1);

Compute the normal time curvature using backward derivatives.

e2 = e1 - e1([end 1:end-1]);

Evolution of the curve.

c = c + dt * e2;

To stabilize the evolution, it is important to re-sample the curve so that it is unit-speed parametrized. You do not need to do it every time step though (to speed up).

c(end+1) = c(1);
d = abs(c(1:end-1)-c(2:end)); d = [0;cumsum(d)];
c = interp1(d/d(end),c,(0:p-1)'/p);

Exercice 1: (the solution is exo1.m) Perform the curve evolution, for a time of Tmax=2. You need to resample it a few times.

exo1;

Geodesic Active Contours

Geodesic active contours minimize a weighted length, where the weight is measured according to some image.

Create a synthetic image with some dots.

n = 200;
nbumps = 40;
theta = rand(nbumps,1)*2*pi;
r = .6*n/2; a = [.62*n .6*n];
x = round( a(1) + r*cos(theta) );
y = round( a(2) + r*sin(theta) );
W = zeros(n); W( x + (y-1)*n ) = 1;
W = perform_blurring(W,10);
W = rescale( -min(W,.05), .3,1);

Display the metric.

clf;
imageplot(W);

Pre-compute the derivatives.

options.order = 2;
G = grad(W, options);
G = G(:,:,1) + 1i*G(:,:,2);

Initialize the curve with a circle.

r = .98*n/2;
p = 128; % number of points on the curve
theta = linspace(0,2*pi,p+1)'; theta(end) = [];
c0 = n/2*(1+1i) +  r*(cos(theta) + 1i*sin(theta));
c = c0;

For this experiment, the time step should be larger (because the curve is in [1,n] x [1,n])

dt = .8;

Display the curve on the back ground;

lw = 2;
clf; hold on;
imageplot(W);
h = plot(imag(c([1:end 1])),real(c([1:end 1])), 'r');
set(h, 'LineWidth', lw);
axis('ij');

Evaluate the gradient.

g = interp2(1:n,1:n, G, imag(c), real(c));

Evaluate the potential.

w = interp2(1:n,1:n, W, imag(c), real(c));

Compute the tangent using forward derivatives.

e1 = c([2:end 1]) - c;
d1 = abs(e1);
e1 = e1 ./ d1;

Compute the normal time curvature using backward derivatives.

e2 = w.*e1 - w([end 1:end-1]).*e1([end 1:end-1]);

Evolution of the curve.

c = c + dt * ( - g .* d1 + e2 );

Exercice 2: (the solution is exo2.m) Perform the curve evolution, for a time of Tmax=1150. Remeber to re-sample the curve several time during the evolution.

exo2;

Medical Image Segmentation

One can use a gradient-based metric to perform edge detection in medical images.

Load an image.

n = 256;
M = rescale( sum(load_image('cortex', n), 3 ) );

Display.

clf;
imageplot(M);

Exercice 3: (the solution is exo3.m) Compute an edge attracting criterion W, that is small in area of strong gradient. You can use, among other, the function grad, perform_blurring, and threshold too large gradients.

exo3;

Exercice 4: (the solution is exo4.m) Create an initial circle c0 of p=128 points.

exo4;

Exercice 5: (the solution is exo5.m) Perform the curve evolution, for a time of Tmax=1150. Remeber to re-sample the curve several time during the evolution. Try with different dynamics for the W scaling so that you capture the contour you are interested in.

exo5;

Evolution of a Non-closed Curve

It is possible to perform the evolution of a non-closed curve by adding boundary constraint (starting and ending points).

In this case, the algorithm find a local minimizer of the geodesic distance between the two points.

Note that a much more efficient way to solve this problem is to use the Fast Marching algorithm to find the global minimizer of the geodesic length.

Load an image.

n = 256;
M = rescale( sum(load_image('cortex', n), 3 ) );
M = M(46:105,61:120);
n = size(M,1);

Display.

imageplot(M);

Exercice 6: (the solution is exo6.m) Compute an edge attracting criterion W, that is small in area of strong gradient. You can use, among other, the function grad, perform_blurring, and threshold too large gradients.

exo6;

Start and end points.

pstart = 4 + 55i;
pend = 53 + 4i;

Initial curve.

p = 128;
t = linspace(0,1,p)';
c0 = t*pend + (1-t)*pstart;

Initialize the evolution.

c = c0;

Display.

clf; hold on;
imageplot(W);
h = plot(imag(c([1:end])),real(c([1:end])), 'r'); set(h, 'LineWidth', 2);
h = plot(imag(c([1 end])),real(c([1 end])), 'b.'); set(h, 'MarkerSize', 30);
axis('ij');

Exercice 7: (the solution is exo7.m) Perform the curve evolution, for a time of Tmax=1000. Be careful to impose the boundary conditions at each step. Remeber to re-sample the curve several time during the evolution.

exo7;